package com.utooo.bid.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.StringUtils;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@ConfigurationProperties(prefix = "thread-pool")
@Data
public class ThreadPoolConfig {
    private Pool bidDocument = new Pool();
    private Pool bidDocumentCatalog = new Pool();
    private Pool common = new Pool();

    @Data
    public static class Pool {
        private int corePoolSize = 5;
        private int maximumPoolSize = 10;
        private int keepAliveTime = 60;
        private int queueCapacity = 100;
        private String threadNamePrefix;
    }

    @Bean("bidDocumentProcessorExecutor")
    public ThreadPoolTaskExecutor bidDocumentProcessorExecutor() {
        return createThreadPoolExecutor(bidDocument, "bid-document-processor-");
    }

    @Bean("bidDocumentCatalogExecutor")
    public ThreadPoolTaskExecutor bidDocumentCatalogExecutor() {
        return createThreadPoolExecutor(bidDocumentCatalog, "bid-document-catalog-processor-");
    }

    @Bean("commonExecutor")
    public ThreadPoolTaskExecutor commonExecutor() {
        return createThreadPoolExecutor(common, "common-task-");
    }

    private ThreadPoolTaskExecutor createThreadPoolExecutor(Pool pool, String defaultNamePrefix) {
        String namePrefix = StringUtils.hasText(pool.getThreadNamePrefix()) ?
                pool.getThreadNamePrefix() : defaultNamePrefix;
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(pool.getCorePoolSize());
        executor.setMaxPoolSize(pool.getMaximumPoolSize());
        executor.setKeepAliveSeconds(pool.getKeepAliveTime());
        executor.setQueueCapacity(pool.getQueueCapacity());
        executor.setThreadNamePrefix(namePrefix);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

